<template>
  <div class="XnyGeneral">
    <!-- <el-button @click="test">test</el-button> -->
    <xny-crud
      ref="xnyCrud"
      v-loading="loading"
      v-bind="$attrs"
      v-on="$listeners"
      :data="crudData"
      :column="crudColumn"
      :option="crudOption"
      :page="crudPage"
      :search.sync="generalSearch"
      :column-option="columnOption"
      :active-tab-prop="activeTabProp"
      :active-tab="activeTab"
      :table-tab-list="tableTabList"
      :search-custom-slot-map="customSlotMap.searchForm"
      @update-column-option="updateColumnOption"
      @update-column-index="updateColumnIndex"
      @update-page="updatePage"
      @on-load="onLoad"
      @search-change="searchChange"
    >
      <!-- 工具栏 左侧-前方 插槽 - 表格切换 -->
      <template #toolbar-menu-left-top>
        <span
          class="tableTab"
          v-if="
            $ocean.vaildData(option.tableTabMenu, config.general.tableTabMenu)
          "
        >
          <el-radio-group
            v-model="activeTab"
            :size="config.size"
            @change="tabChange"
          >
            <template v-for="(item, index) in tableTabList">
              <el-radio-button
                :label="item.label"
                :key="'tableTab' + index"
                v-if="item.type == 1"
                plain
              ></el-radio-button>
            </template>
          </el-radio-group>
          <el-divider direction="vertical"></el-divider>
        </span>
      </template>
      <!-- 工具栏 左侧-后方 插槽 - 功能按钮 -->
      <template #toolbar-menu-left="scope"
        ><slot name="toolbar-menu-left" v-bind="scope"
      /></template>
      <!-- 表格数据栏 操作列-左测 插槽 -->
      <template #table-menu-left="scope"
        ><slot name="table-menu-left" v-bind="scope"
      /></template>
      <!-- 表格数据栏 操作列-右测 插槽 -->
      <template #table-menu-right="scope"
        ><slot name="table-menu-right" v-bind="scope"
      /></template>
      <template #table-top="scope"
        ><slot name="table-top" v-bind="scope"
      /></template>
      <!-- 搜索项、表格数据列 插槽 -->
      <template v-for="item in slotList" #[item.name]="scope">
        <slot :name="item.innerName" v-bind="scope" />
      </template>
    </xny-crud>
  </div>
</template>

<script>
import config from '../../config'
import mockOption from './mock/option'
import mockData from './mock/data'
// import mockOption from './mock/Wt-20220224'
// import mockData from './mock/data-20220225'
import customSlotMap from './customSlotMap'

export default {
  name: 'XnyGeneral',
  data() {
    return {
      config,
      customSlotMap,
      dataInit: false,
      isOptionInit: false,
      loading: true,
      activeTab: '', // 选中tab
      tableTabList: [], // tab列表
      toolbarOption: { common: {} }, // 工具栏配置
      searchOption: { common: null }, // 搜索栏配置
      tableOption: { common: {} }, // 表格配置
      columnOption: {}, // 列配置
      pageOption: {}, // 分页配置
      tableData: {}, // 表格数据
      crudData: [],
      crudPage: {},
      query: {},
      generalSearch: {},
      originInfo: null, // 接口返回表格配置
      originData: null, // 接口返回表格数据
    }
  },
  props: {
    // ajax方法
    request: {
      type: Function,
      // required: true,
    },
    // url信息
    urlInfo: {
      type: Object,
      // required: true,
    },
    option: {
      type: Object,
      default: () => {},
    },
    // 外部自定义请求参数
    customRequestParam: {
      type: Object,
      default: () => {},
    },
    search: {
      type: Object,
      default: () => ({}),
    },
  },
  components: {},
  watch: {
    generalSearch: {
      handler(val, oldVla) {
        if (val != oldVla) this.$emit('update:search', val)
      },
    },
    search: {
      handler(val) {
        if (val != this.generalSearch) this.generalSearch = val
      },
    },
    tableData: {
      handler() {
        this.setTableData()
      },
    },
    activeTab: {
      handler() {
        this.setTableData()
        this.setPage()
        this.$nextTick(() => {
          this.$refs?.xnyCrud?.setSearchDefault()
          this.query = this.$ocean.deepClone(this.generalSearch)
          this.$refs.xnyCrud.refreshTable()
        })
      },
    },
  },
  computed: {
    activeTabProp() {
      if (
        !this.tableTabList ||
        this.tableTabList.length == 0 ||
        !this.activeTab
      ) {
        return ''
      }
      return this.tableTabList.find((tab) => tab.label == this.activeTab).prop
    },
    crudOption() {
      let activeTable
      if (!this.activeTabProp) activeTable = {}
      else activeTable = this.tableOption[this.activeTabProp]
      return {
        ...this.tableOption.common,
        ...activeTable,
        ...this.option,
      }
    },
    crudColumn() {
      if (!this.activeTabProp) return []
      const column = this.columnOption[this.activeTabProp] || []
      column.forEach((el, index) => {
        if (this.$ocean.validatenull(el.index)) el.index = index
      })
      column.sort((firstEl, secondEl) =>
        this.$ocean.vaildData(secondEl.index, Infinity) >
        this.$ocean.vaildData(firstEl.index, Infinity)
          ? -1
          : 1
      )
      const commonSearch = this.searchOption.common || []
      const activeSearch = this.searchOption[this.activeTabProp] || []
      return [...column, ...commonSearch, ...activeSearch] || []
    },
    // 插槽列表
    slotList() {
      let searchList = []
      let slotList = []
      let slotName
      let tempSlot
      // 搜索栏插槽
      Object.keys(this.searchOption).forEach((key) => {
        if (this.searchOption[key])
          searchList = [...searchList, ...this.searchOption[key]]
      })
      searchList.forEach((search) => {
        slotName = 'search-' + search.prop
        if (this.$scopedSlots[slotName]) {
          tempSlot = {
            name: slotName,
            innerName: slotName,
            label: search.label,
            prop: search.prop,
            type: 'search-item',
          }
          slotList.push(tempSlot)
        }
      })
      // 表格列插槽
      this.columnOption[this.activeTabProp]?.forEach((column) => {
        slotName = 'table-' + this.activeTabProp + '-' + column.prop
        // slotName = column.prop
        if (this.$scopedSlots[slotName]) {
          tempSlot = {
            name: 'table-' + column.prop,
            innerName: slotName,
            label: column.label,
            prop: column.prop,
            type: 'column-item',
          }
          slotList.push(tempSlot)
        }
      })
      return slotList
    },
  },
  methods: {
    test() {
      this.columnOption[this.activeTabProp][2].index = 1
      this.$refs.xnyCrud.refreshTable()
    },
    // 外部指定组件配置
    setOriginInfo(originInfo) {
      this.getOption({ originInfo })
    },
    // 外部指定组件数据
    setOriginData(originData) {
      this.onLoad({ originData })
    },
    // 获取表格数据
    getData(rowIndex) {
      return this.$refs.xnyCrud.getData(rowIndex)
    },
    // 设置行为选中状态，第二个参数为选中与否
    setCheckboxRow(rows, checked) {
      this.$refs.xnyCrud.setCheckboxRow(rows, checked)
    },
    // 外部搜索
    searchData(param) {
      Object.keys(param).forEach((key) => {
        this.generalSearch[key] = param[key]
      })
      // 方法一：单次刷新数据，isRefesh传false则会保留当前页码
      // this.$refs.xnyGeneral.onLoad({ query: param, isRefesh: true });
      // 方法二：会记录搜索条件
      this.searchChange(param)
    },
    // 修改列顺序
    updateColumnIndex({ newIndex, oldIndex, tabProp }) {
      const currRow = this.columnOption[tabProp].splice(oldIndex, 1)[0]
      this.columnOption[tabProp].splice(newIndex, 0, currRow)
      this.columnOption[tabProp].forEach((el, index) => {
        el.index = index
      })
      this.$refs.xnyCrud.refreshTable()
    },
    // 修改列配置
    updateColumnOption(param) {
      // console.log('新列配置参数：', param)
      if (!param.tabProp || !param.prop || !param.attrs) return
      this.columnOption[param.tabProp].forEach((el) => {
        if (el.prop == param.prop) {
          el[param.attrs] = param.val
          // console.log(el)
        }
      })
      this.$refs.xnyCrud.refreshTable()
      // console.log(this.columnOption[param.tabProp])
    },
    // 搜索回调
    searchChange(searchParam) {
      // console.log('搜索参数：', searchParam)
      this.query = this.$ocean.deepClone(searchParam)
      if (this.activeTabProp)
        this.pageOption[this.activeTabProp].currentPage = 1
      this.onLoad()
    },
    // 更新分页信息
    setPage() {
      if (!this.activeTabProp) {
        this.crudPage = {}
      }
      this.crudPage = this.pageOption[this.activeTabProp] || {}
      // console.log('更新分页信息', this.crudPage)
    },
    // 更新表格数据
    setTableData() {
      if (!this.activeTabProp) {
        this.crudData = []
      }
      this.crudData = this.tableData[this.activeTabProp] || []
    },
    // 分页发生变化
    updatePage(page) {
      // console.log('分页发生变化：', JSON.stringify(page))
      this.pageOption[this.activeTabProp] = this.$ocean.deepClone(page)
    },
    // 计算load参数
    calcLoadParam(pages, query) {
      const webTableTabQuery = []
      let tabQuery
      let webTableTabFilterQuery
      let tempSearch
      // -------- 计算分页信息及搜索条件 ----------
      Object.keys(pages).forEach((key) => {
        webTableTabFilterQuery = []
        this.searchOption.common?.forEach((search) => {
          tempSearch = {
            id: Number(search.prop),
            value: query[search.prop] || '',
          }
          webTableTabFilterQuery.push(tempSearch)
        })
        this.searchOption[key]?.forEach((search) => {
          let value
          if (search.type == 'textarea')
            value = this.$ocean.specialStrFilter(query[search.prop])
          else value = query[search.prop] || ''
          tempSearch = {
            id: Number(search.prop),
            value,
          }
          webTableTabFilterQuery.push(tempSearch)
        })
        tabQuery = {
          tabName: key,
          pageNo: pages[key].currentPage || 1,
          pageSize: pages[key].pageSize || 10,
          webTableTabFilterQuery,
        }
        webTableTabQuery.push(tabQuery)
      })
      // -------------------------------------------
      const param = {
        webTableName: this.tableOption.common.tableName,
        webTableTabQuery,
      }
      return param
    },
    // 加载数据
    async onLoad(option) {
      if (!this.isOptionInit) throw new Error('表格配置未初始化')
      this.loading = true
      if (option?.isRefresh) this.pageOption[this.activeTabProp].currentPage = 1
      let param
      if (this.dataInit) {
        // 非首次加载数据
        param = this.calcLoadParam(
          { [this.activeTabProp]: this.pageOption[this.activeTabProp] },
          { ...this.query, ...(option?.query || {}) }
        )
      } else {
        param = this.calcLoadParam(this.pageOption, this.generalSearch)
        // this.dataInit = true
      }
      // --------------------------------------------
      let res
      if (this.request)
        res = await this.request({
          ...this.urlInfo.dataUrl,
          data: { ...param, ...this.customRequestParam },
        })
      else res = mockData
      // const res = mockData
      // --------------------------------------------
      let tempDataList
      if (option?.originData) {
        tempDataList = option.originData
      } else {
        tempDataList = res.data.tabList
      }
      this.originData = this.$ocean.deepClone(tempDataList)

      const done = (dataList = tempDataList) => {
        let tempData
        dataList.forEach((tabData) => {
          this.pageOption[tabData.tabName].total = tabData.totalRowCount || 0
          tempData = {}
          this.tableData[tabData.tabName] = []
          tabData.rowList.forEach((item) => {
            tempData = {
              rowKey: item.rowKey,
            }
            item.fieldList.forEach((el) => {
              tempData[el.fieldNameCamel || el.fieldName] =
                el.textValue || el.displayText
            })
            this.tableData[tabData.tabName].push(tempData)
          })
        })
        this.loading = false
        this.$nextTick(() => {
          this.setTableData()
          this.setPage()
        })
      }
      const loading = () => {
        this.loading = false
      }

      if (this._events['update-data']) {
        this.$emit('update-data', {
          data: tempDataList,
          done,
          loading,
          first: !this.dataInit,
        })
      } else {
        done()
      }
      this.dataInit = true
    },
    // 配置初始化
    async optionInit() {
      await this.getOption()
      if (this.$ocean.vaildData(this.option.initialLoad, true)) {
        this.$nextTick(() => {
          this.$refs?.xnyCrud?.setSearchDefault()
          this.onLoad()
        })
      } else this.loading = false
      this.$emit('option-init')
    },
    // 获取表格配置
    async getOption(param) {
      this.loading = true
      // --------------------------------------------------
      let res
      if (this.request) {
        let requestParam = {
          ...this.urlInfo.optionUrl,
          data: {
            ...this.customRequestParam,
            webTableName: this.urlInfo.optionUrl.webTableName,
          },
        }
        res = await this.request(requestParam)
      } else res = mockOption
      // const res = mockOption
      // --------------------------------------------------
      let option
      if (param?.originInfo) {
        option = param.originInfo
      } else {
        option = res.data
      }
      this.originInfo = this.$ocean.deepClone(option)

      const dicDataList = {}
      option?.dictList?.forEach((item) => {
        dicDataList[item.dictCode] = item.valueList
      })
      // 表格公共配置
      this.tableOption.common = {
        tableDisplayName: option.tableDisplayName || '表格名称',
        tableName: option.tableName, // tableProp
        tableType: option.tableType || 'Normal', // 表格类型
        showSearch: option.hasBlockSearch, // 是否有查询块
      }
      // 读取tabList
      this.tableTabList = []
      let tabItem
      let columnItem
      let columns
      let table
      let page
      const normalTab = [] // 普通tab列表
      // 公共搜索条件
      this.searchOption.common = this.searchFilter(option.filterList)
      // tab循环
      option.tabList.forEach((tab, tabIndex) => {
        // tab配置
        tabItem = {
          label: tab.tabDisplayName || '表格名称',
          prop: tab.tabName,
          // type: tab.tabType || '1', // 1：Normal-普通；2：Extend-展开
          type: '1', // 1：Normal-普通；2：Extend-展开
        }
        this.tableTabList.push(tabItem)
        if (tabItem.type == '1') normalTab.push(tabItem)
        // 列配置
        columns = []
        tab.fieldList.forEach((column, index) => {
          columnItem = {
            label: column.fieldDisplayName,
            prop: column.fieldNameCamel || column.fieldName,
            index: this.$ocean.vaildData(column.index, index),
            hide: column.hiddenFlag,
            fixed: column.frozenFlag, // 列冻结
            width: column.widthPixel,
          }
          // -------------------------------------------------
          // if (tabIndex == 0 && index == 0 && text) columnItem.label = text
          // -------------------------------------------------
          if (column.dictCode) {
            columnItem.type = 'select'
            columnItem.dicData = dicDataList[column.dictCode]
            columnItem.props = { label: 'valueName', value: 'valueCode' }
            // console.log(option.dictList, dicDataList[column.dictCode])
          }

          columns.push(columnItem)
        })
        this.columnOption[tab.tabName] = columns
        // 表格个性配置
        table = {
          showPagination: tab.hasBlockPage, // 是否显示分页
          selection: tab.hasBlockSelect, // 表格勾选列
          isCurrent: tab.radioFlag, // 高亮显示选中行
        }
        this.tableOption[tab.tabName] = table
        // 分页配置
        page = {
          total: 0, // 总条目数
          currentPage: 1, // 当前页数
          pageSize: tab.rowCountPerPage, // 每页显示条目个数
          pageSizes: tab.rowCountPerPageList, // 每页显示个数选择器的选项设置
        }
        this.pageOption[tab.tabName] = page
        // 个性搜索条件
        this.searchOption[tab.tabName] = this.searchFilter(tab.filterList)
      })
      // 设置默认选中tab
      const isActiveTab = normalTab.some((el) => el.label == this.activeTab)
      if (!isActiveTab) this.activeTab = normalTab[0].label

      this.isOptionInit = true

      this.loading = false

      // console.log(option)
      // console.log(this.tableTabList)
      // console.log(this.columnOption)
      // console.log(this.searchOption)
    },
    // 搜索条件处理
    searchFilter(seachList) {
      const result = []
      let temp
      let value = ''
      seachList.forEach((item) => {
        const multipleValueType = [
          'MultiSelection',
          'IntScope',
          'DateScope',
          'TimeScope',
          'MultiLike',
        ]
        if (item.defaultValueList.join && item.defaultValueList.length > 0) {
          if (
            item.defaultValueList.length < 2 &&
            multipleValueType.includes(item.filterType)
          )
            item.defaultValueList.push('')
          value = item.defaultValueList.join(',')
        } else value = item.defaultValueList.toString()
        temp = {
          hide: true,
          showColumn: false,
          search: true,
          prop: item.filterId.toString(),
          label: item.filterDisplayName,
          searchType: item.filterType, // 类型，多行文本未实现
          searchSpan: item.searchSpan || item.widthPixelInput || 6, // 需要讨论(1-24) 6 = 20% 4 6 8 12 24
          // searchSpan: 6,
          searchLabelWidth: item.widthPixelLabel,
          // searchLabelWidth: 50,
          dicData: item.optionList || [],
          props: config.general.props,
          defaultValueList: item.defaultValueList,
          value,
        }
        const avueFormSlotList = Object.keys(customSlotMap.avueForm)
        if (avueFormSlotList.includes(item.filterType)) {
          temp = { ...temp, ...customSlotMap.avueForm[item.filterType] }
        }
        result.push(temp)
      })
      return result
    },
    // 表格tab发生切换
    tabChange(label) {
      // console.log(`切换到tab：${label}`)
      let activeTab = this.tableTabList.find((item) => {
        return item.label == label
      })
      this.$emit('tabChange', activeTab.prop)
      this.$emit('tab-change', activeTab.prop)
    },
  },
  created() {
    this.optionInit()
  },
  mounted() {},
}
</script>

<style scoped lang="scss">
.XnyGeneral {
  .tableTab {
    // width: calc(100% - 8px);
    // padding: 4px;
  }
  height: 100%;
  overflow: auto;
}
</style>
